/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <iostream>
#include "slot_info/slot_info_static.h"
#include "log/log.h"
#include <fcntl.h>

namespace Updater {
#define MISC_DEVICE_NODE "/dev/block/by-name/bootctrl"
constexpr int32_t UPDATE_PARTITION_A = 1;
constexpr int32_t UPDATE_PARTITION_AB = 2;
constexpr off_t MISC_PARTITION_ACTIVE_SLOT_OFFSET = 1024;
constexpr off_t MISC_PARTITION_ACTIVE_SLOT_SIZE = 4;

#ifndef UPDATER_AB_SUPPORT
void GetPartitionSuffixStatic(std::string &suffix)
{
    suffix = "";
}
void GetActivePartitionSuffixStatic(std::string &suffix)
{
    suffix = "";
}
#else
static int ReadMisc(off_t offset, off_t size)
{
    int fd = open(MISC_DEVICE_NODE, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (fd < 0) {
        return -1;
    }
    if (lseek(fd, offset, SEEK_SET) < 0) {
        LOG(ERROR) << "Failed lseek miscDevice";
        close(fd);
        return -1;
    }
    int32_t slot = 0;
    if (read(fd, &slot, size) != size) {
        LOG(ERROR) <<"Failed read migic miscDevice";
        close(fd);
        return -1;
    }
    LOG(INFO) << "Read slot:" << slot;
    close(fd);
    return slot;
}

void GetPartitionSuffixStatic(std::string &suffix)
{
    // 1. 通过popen执行cat命令获取cmdline内容
    int32_t current_slot = ReadMisc(MISC_PARTITION_ACTIVE_SLOT_OFFSET, MISC_PARTITION_ACTIVE_SLOT_SIZE);

    LOG(INFO) << "current_slot: " << current_slot;

    // 4. 校验槽位有效性
    if (current_slot < UPDATE_PARTITION_A || current_slot > UPDATE_PARTITION_AB) {
        LOG(ERROR) << "Invalid slot value: " << current_slot << ", expected 1 or 2";
        suffix = "";
        return;
    }

    // 5. 生成目标分区后缀（取反当前槽位）
    suffix = (current_slot == UPDATE_PARTITION_A) ? "_b" : "_a";
    LOG(INFO) << "Active slot: " << current_slot << ", target suffix: " << suffix;
}

void GetActivePartitionSuffixStatic(std::string &suffix)
{
    // 1. 通过popen执行cat命令获取cmdline内容
    int32_t current_slot = ReadMisc(MISC_PARTITION_ACTIVE_SLOT_OFFSET, MISC_PARTITION_ACTIVE_SLOT_SIZE);

    LOG(INFO) << "current_slot: " << current_slot;

    // 4. 校验槽位有效性
    if (current_slot < UPDATE_PARTITION_A || current_slot > UPDATE_PARTITION_AB) {
        LOG(ERROR) << "Invalid slot value: " << current_slot << ", expected 1 or 2";
        suffix = "";
        return;
    }

    // 5. 生成目标分区后缀
    suffix = (current_slot == UPDATE_PARTITION_A) ? "_a" : "_b";
    LOG(INFO) << "Active slot: " << current_slot << ", target suffix: " << suffix;
}
#endif
} // updater